package com.th.supcom.pds.impl.service.internal.phamapply;

import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.th.supcom.pds.domain.pojo.InpPhamApplyDetailSummary;
import com.th.supcom.pds.domain.pojo.PdsPatPhamRemain;
import com.th.supcom.pds.domain.vo.InpPhamApplyDetailVO;
import com.th.supcom.pds.impl.common.enums.AvailableEnum;
import com.th.supcom.pds.impl.common.enums.NoDispenseReason;

public final class CalculatePhamAmountAndCost
{
    /** 日志记录器. */
    public static final Logger s_logger = LoggerFactory.getLogger (CalculatePhamAmountAndCost.class);

    private CalculatePhamAmountAndCost ()
    {

    }

    /**
     * 获取所有患者药品的摆药数量
     * 
     * @param lefts
     * @param detailListMap
     * @param phams
     * @param patSource true是门诊，false 是住院
     */
    public static void getDispenseCount (List <PdsPatPhamRemain> lefts, Map <Long, List <InpPhamApplyDetailVO>> detailListMap,
                                         List <InpPhamApplyDetailSummary> phams, boolean isNight)

    {
        Map <Long, List <PdsPatPhamRemain>> leftListMap = PhamApplyConvertUtils.convertPhamLeftListToMapByPaivisitId (lefts);
        Map <String, InpPhamApplyDetailSummary> phamListMap = PhamApplyConvertUtils.convertPhamInfoListToMapByPhamStdCode (phams);

        // 如果是晚上则对每个患者单个医嘱药品摆药数量进行计算，且用最小包装单位
        for (Map.Entry <Long, List <InpPhamApplyDetailVO>> entry : detailListMap.entrySet ())
        {
            List <PdsPatPhamRemain> leftList = leftListMap.get (entry.getKey ());
            Map <String, PdsPatPhamRemain> leftMap = PhamApplyConvertUtils.convertPhamLeftListToMapByPhamStdCode (leftList);

            // 按照医嘱序号进行分组
            Map <Long, List <InpPhamApplyDetailVO>> detailOrderNoMap = PhamApplyConvertUtils.convertListToMapByOrderNo (entry.getValue ());
            getDispenseCountByPaiVisitId (leftMap, phamListMap, detailOrderNoMap, isNight);

        }
    }

    /**
     * 计算单个患者的摆药数量
     * 
     * @param leftMap
     * @param phamMap
     * @param detailMap
     * @param isNight
     * @param patSource true是门诊，false 是住院
     */
    private static void getDispenseCountByPaiVisitId (Map <String, PdsPatPhamRemain> leftMap, Map <String, InpPhamApplyDetailSummary> phamMap,
                                                      Map <Long, List <InpPhamApplyDetailVO>> detailMap, boolean isNight)
    {
        // 循环每个医嘱
        for (Map.Entry <Long, List <InpPhamApplyDetailVO>> entry : detailMap.entrySet ())
        {
            Map <Long, List <InpPhamApplyDetailVO>> detailOrderSubNoMap = PhamApplyConvertUtils.convertListToMapByOrderSubNo (entry.getValue ());
            getDispenseCountByOrderNo (leftMap, phamMap, detailOrderSubNoMap, isNight);
        }
    }

    /**
     * 计算单个患者单个子医嘱的摆药数量
     * 
     * @param leftMap
     * @param phamMap
     * @param detailMap
     * @param isNight
     * @param patSource true是门诊，false 是住院
     */
    public static void getDispenseCountByOrderNo (Map <String, PdsPatPhamRemain> leftMap, Map <String, InpPhamApplyDetailSummary> phamMap,
                                                  Map <Long, List <InpPhamApplyDetailVO>> detailMap, boolean isNight)
    {
        // 循环每个子医嘱
        for (Map.Entry <Long, List <InpPhamApplyDetailVO>> entry : detailMap.entrySet ())
        {
            // 按照药品进行分组
            Map <String, List <InpPhamApplyDetailVO>> detailByPhamMap = PhamApplyConvertUtils.convertListToMapByPhamStdCode (entry.getValue ());
            getDispenseCountByOrderSubNO (leftMap, phamMap, detailByPhamMap, isNight);
        }
    }

    /**
     * 计算单个患者单个子医嘱单个药品的数量
     * 
     * @param leftMap
     * @param phamMap
     * @param detailMap
     * @param isNight
     * @param patSource true是门诊，false是住院
     */
    private static void getDispenseCountByOrderSubNO (Map <String, PdsPatPhamRemain> leftMap, Map <String, InpPhamApplyDetailSummary> phamMap,
                                                      Map <String, List <InpPhamApplyDetailVO>> detailMap, boolean isNight)
    {
        // 计算单个患者单个子医嘱单个药品的数量
        for (Map.Entry <String, List <InpPhamApplyDetailVO>> phamEntry : detailMap.entrySet ())
        {
            InpPhamApplyDetailSummary pham = phamMap.get (phamEntry.getKey ());
            List <InpPhamApplyDetailVO> temp = phamEntry.getValue ();
            if (null == pham || temp.isEmpty ())
            {
                continue;
            }

            PdsPatPhamRemain left = leftMap.get (pham.getPhamStdCode ());
            // 如果是大包装小剂量的药品
            int count = 0;

            if (AvailableEnum.YES.getEnumCode ().equals (pham.getLargePackageSmallDosage ()))
            {
                count = getLargePackageDispenseCount (left, pham, temp);
                setDispenseCount (pham, temp, count, isNight);
                continue;
            }

            // 如果是可分割的药品
            if (AvailableEnum.YES.getEnumCode ().equals (pham.getSplitType ()))
            {
                count = getDivisibleDispenseCount (pham, temp);
            }
            else
            {
                count = getUnDivisibleDispenseCount (pham, temp);
            }
            setDispenseCount (pham, temp, count, isNight);
        }
    }

    /**
     * 设置摆药数量
     * 
     * @param pham
     * @param detailVOList
     * @param count
     * @param isNight
     */
    public static void setDispenseCount (InpPhamApplyDetailSummary pham, List <InpPhamApplyDetailVO> detailVOList, int count, boolean isNight)
    {
        int applyAmount = 0;
        String appUnit = "";
        double price = 0.0;
        double sumDosage = 0.0;
        int factor = 1;

        if (isNight)
        {
            if (AvailableEnum.YES.getEnumCode ().equals (pham.getLargePackageSmallDosage ()))
            {
                applyAmount = (int) Math.ceil ((double) count);
            }
            else
            {
                applyAmount = (int) Math.ceil (count / pham.getPackageFactor ());
            }
            factor = pham.getPackageFactor ().intValue ();
            appUnit = pham.getPackageUnit ();
            price = pham.getRetailPrice ();
            sumDosage = count * pham.getPackageFactor ();
        }
        else
        {
            if (AvailableEnum.YES.getEnumCode ().equals (pham.getLargePackageSmallDosage ()))
            {
                price = pham.getRetailPrice ();
                appUnit = pham.getPackageUnit ();
                sumDosage = count * pham.getPackageFactor ();
                factor = pham.getPackageFactor ().intValue ();
            }
            else
            {
                price = pham.getPhamPrice ();
                appUnit = pham.getPhamUnit ();
                sumDosage = count;
            }
            applyAmount = count;
        }

        for (InpPhamApplyDetailVO detailVO : detailVOList)
        {
            detailVO.setApplyAmount (applyAmount);
            detailVO.setFactor (factor);
            detailVO.setCosts (applyAmount * price);
            detailVO.setCharges (applyAmount * price);
            detailVO.setApplyUnit (appUnit);
            detailVO.setDosageSum (sumDosage);
            detailVO.setScheduleCount (detailVOList.size ());
            detailVO.setApplySupplyFlag (pham.getApplySupplyFlag ());
        }
    }

    /**
     * 计算一种大容量小剂量药品的摆药数量
     * 
     * @param left 药品剩余剂量
     * @param pham 药品基本属性
     * @param order 医嘱信息
     * @return
     */
    private static int getLargePackageDispenseCount (PdsPatPhamRemain left, InpPhamApplyDetailSummary pham, List <InpPhamApplyDetailVO> detailVOList)
    {
        // 需要申请的总量 sumDosage
        double sumDosage = 0.0;

        for (InpPhamApplyDetailVO vo : detailVOList)
        {
            sumDosage += vo.getDosage ();
        }

        double leftDosage = 0.0;

        if (null != left)
        {
            leftDosage = left.getAmountLeft ();
        }

        double diff = sumDosage - leftDosage;

        if (diff <= 0.0)
        {
            for (InpPhamApplyDetailVO vo : detailVOList)
            {
                vo.setDispenseResultFlag (AvailableEnum.NO.getEnumCode ());
                vo.setNoDispenseMemo (NoDispenseReason.LEFT_ENOUGH.getEnumName ());
            }
        }

        // 此处应该计算患者药品申请总量出去剩余数量后的
        double count = sumDosage / (pham.getDosagePerUnit () * pham.getPackageFactor ());
        return (int) Math.ceil (count);

    }

    /**
     * 计算一种可分割药品的摆药数量
     * 
     * @param pham 药品基本属性
     * @param order 医嘱信息
     * @return
     */
    private static int getDivisibleDispenseCount (InpPhamApplyDetailSummary pham, List <InpPhamApplyDetailVO> detailVOList)
    {
        // 需要申请的总量 sumDosage
        double sumDosage = 0.0;

        for (InpPhamApplyDetailVO vo : detailVOList)
        {
            sumDosage += vo.getDosage ();
        }

        // 将计算得到的申请总量记录下来
        for (InpPhamApplyDetailVO vo : detailVOList)
        {
            vo.setDosageSum (sumDosage);
        }

        double count = sumDosage / pham.getDosagePerUnit ();
        return (int) Math.ceil (count);
    }

    /**
     * 计算不可分割药品的摆药数量
     * 
     * @param pham 药品基本属性
     * @param order 医嘱信息
     * @return
     */
    private static int getUnDivisibleDispenseCount (InpPhamApplyDetailSummary pham, List <InpPhamApplyDetailVO> detailVOList)
    {
        // 需要申请的总量 sumDosage
        int sumCount = 0;

        for (InpPhamApplyDetailVO vo : detailVOList)
        {
            double count = vo.getDosage () / pham.getDosagePerUnit ();
            sumCount += (int) Math.ceil (count);
        }

        return sumCount;
    }

    /** 公司版权信息. */
    public static final String copyright = "Copyright 2014, XuNuo Corporation";

    /** 提交路径. */
    public static final String SCC_BRANCH = "$URL$";

    /** 提交日期. */
    public static final String SCC_LAST_MODIFICATION_DATE = "$Date$";

    /** 最终修改人员. */
    public static final String SCC_LAST_MODIFIER_NAME = "$Author$";

    /** 最终版本号. */
    public static final String SCC_REVISION = "$Revision$";
}
